package com.guyu.plugin.password.generator;


import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.guyu.plugin.password.AbstractPassword;
import com.guyu.plugin.password.crypto.PasswordCrypto;
import com.guyu.plugin.password.exception.PasswordException;

/**
 * <p> 简单密码生成 </p>
 * 明文密码规则：密码由[minLength,maxLength]位字母/数字组成
 * 前端密码加密规则：明文密码+13位时间戳，加密算法自定义，默认国密SM2
 * 密码摘要：加密算法自定义，默认国密SM3
 *
 * @date 2023/8/10
 */
public class DefaultPassword extends AbstractPassword {
    private static final long serialVersionUID = 7993341549455448972L;
    /**
     * 时间戳长度
     */
    private static final int TIMESTAMP_LENGTH = 13;
    /**
     * 密码验证最大超时时间,默认5分钟
     */
    private static final int PASSWORD_VERIFY_TIMEOUT = 5 * 60 * 1000;
    /**
     * 密码正则
     * 1.密码由8-16位字母/数字组成
     * ^[0-9A-Za-z]{8,16}$
     * 2.包含大小写字母和数字的组合，不能使用特殊字符，长度在 8-16 之间
     * ^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[a-zA-Z0-9]{8,16}$
     * 3.包含大小写字母和数字的组合，可以使用特殊字符，长度在8-16之间
     * ^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,16}$
     */
    private String regex;
    /**
     * 校验密码错误信息
     */
    private String errMsg;

    public DefaultPassword(String publicKeyStr, String privateKeyStr, String salt) {
        super(publicKeyStr, privateKeyStr, salt);
    }

    public DefaultPassword(String publicKeyStr, String privateKeyStr, String salt, int minLength, int maxLength) {
        super(publicKeyStr, privateKeyStr, salt, minLength, maxLength);
    }

    public DefaultPassword(PasswordCrypto generator, int minLength, int maxLength) {
        super(generator, minLength, maxLength);
        this.regex = "^[0-9A-Za-z]{" + minLength + "," + maxLength + "}$";
        this.errMsg = "密码由" + minLength + "-" + maxLength + "位字母/数字组成";
    }

    @Override
    protected String encryptRule(String password) {
        long timestamp = System.currentTimeMillis();
        return password + timestamp;
    }

    @Override
    protected String decryptRule(String decryptStr) {
        //密码长度【min-max】+时间戳长度
        if (decryptStr.length() < minLength + TIMESTAMP_LENGTH || decryptStr.length() > maxLength + TIMESTAMP_LENGTH) {
            throw new PasswordException(errMsg);
        }
        String timestampStr;
        long timestamp;
        try {
            timestampStr = StrUtil.subSufByLength(decryptStr, TIMESTAMP_LENGTH);
            timestamp = Long.parseLong(timestampStr);
        } catch (Exception e) {
            throw new PasswordException(errMsg);
        }
        //时间相差超过5分钟，则让用户重新提交
        if (System.currentTimeMillis() - timestamp > PASSWORD_VERIFY_TIMEOUT) {
            throw new PasswordException("请求已过期");
        }

        return StrUtil.removeSuffix(decryptStr, timestampStr);
    }

    @Override
    protected String createPassword() {
        return RandomUtil.randomString(8);
    }

    public boolean check(String password) {
        if (!ReUtil.isMatch(regex, password)) {
            throw new PasswordException(errMsg);
        }
        return true;
    }
}
